package com.zcx.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

/**
 * @author zcx
 * @Title MySql配置
 * @date 2018年12月04日 17:28
 **/
@Configuration
//@EnableTransactionManagement  //注解是为了增加事务的支持
@MapperScan(value = "com.zcx.demo.dao",sqlSessionFactoryRef = "sqlSessionFactory")//自动扫描，就不用一个个接口来添加了
@PropertySource("classpath:db.properties")
public class MysqlConfig {
    @Value("${driverClassName}")
    private String jdbcDriver;

    @Value("${dbUsername}")
    private String username;

    @Value("${dbPassword}")
    private String password;

    @Value("${url}")
    private String jdbcUrl;

    //最小、最大
    @Value("${minIdle}")
    private String minIdle;

    @Value("${maxActive}")
    private String maxActive;

    @Value("${maxWait}")
    private String maxWait;     //配置获取连接等待超时的时间

    @Value("${validationQuery}")
    private String validationQuery;

    @Value("${testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${testOnReturn}")
    //@Value(false)
    private boolean testOnReturn;

    @Value("${testWhileIdle}")
    private boolean testWhileIdle;

    //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
    @Value("${timeBetweenEvictionRunsMillis}")
    private long timeBetweenEvictionRunsMills;

    //配置一个连接在池中最小生存的时间，单位是毫秒
    @Value("${minEvictableIdleTimeMillis}")
    private long minEvictableTimeMills;

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(this.jdbcDriver);
        dataSource.setUsername(this.username);
        dataSource.setPassword(this.password);
        dataSource.setUrl(this.jdbcUrl);
        dataSource.setMaxActive(Integer.valueOf(this.maxActive));
        dataSource.setValidationQuery(this.validationQuery);
        dataSource.setTestOnBorrow(this.testOnBorrow);
        dataSource.setTestOnReturn(this.testOnReturn);
        dataSource.setTestWhileIdle(this.testWhileIdle);
        dataSource.setTimeBetweenConnectErrorMillis(this.timeBetweenEvictionRunsMills);
        dataSource.setMinEvictableIdleTimeMillis(minEvictableTimeMills);
        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxOpenPreparedStatements(20);
        dataSource.setInitialSize(50);
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        //扫描xml映射文件的路径
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappings/*.xml"));
        //typeAliasesPackage：它一般对应我们的实体类所在的包，这个时候会自动取对应包中不包括包名的简单类名作为包括包名的别名。多个package之间可以用逗号或者分号等来进行分隔。(value的值一定要是包的全名)
        sessionFactory.setTypeAliasesPackage("com.zcx.demo");
        sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:mybatis-config.xml"));
        return sessionFactory.getObject();
    }
}
